/**
 * Moondance UML modeling tool
 * 
 * This program is free software; you can redistribute it and
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 3
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

package ro.pub.cs.se.moondance.model;

import java.util.ArrayList;

import org.eclipse.swt.graphics.Image;

public abstract class UMLBaseClass extends UMLEntity {
	private static final long serialVersionUID = 2071941514972902536L;
	private ModelElement parent;// UMLDiagram or UMLPackage
	private String visibility;
	private String name;
	private ArrayList<ClassVariable> attributes = new ArrayList<ClassVariable>();
	private ArrayList<ClassFunction> operations = new ArrayList<ClassFunction>();
	private boolean isAbstractClass;
	private boolean isInterfaceClass;

	private ArrayList<UMLClass> extendedClasses = new ArrayList<UMLClass>();
	private ArrayList<UMLInterface> implementedInterfaces = new ArrayList<UMLInterface>();

	// visibility <<interface>>/<<abstract>> name

	public UMLBaseClass() {
		super();
	}

	public UMLBaseClass(String name, String visibility,
			boolean isInterfaceClass, boolean isAbstractClass,
			ModelElement parent) {
		super();
		if (name == null)
			throw new NullPointerException("Name cannot be null");
		if (visibility == null)
			throw new NullPointerException("Visibility cannot be null");
		if (!VisibilityType.contains(visibility))
			throw new IllegalArgumentException("Visibility type unknown");
		this.name = name;
		this.visibility = visibility;
		this.isInterfaceClass = isInterfaceClass;
		this.isAbstractClass = isAbstractClass;
		this.parent = parent;
	}

	public void setVisibility(String visibility) {
		this.visibility = visibility;
	}

	public void setInterfaceClass(boolean isInterfaceClass) {
		this.isInterfaceClass = isInterfaceClass;
	}

	public void setAbstractClass(boolean isAbstractClass) {
		this.isAbstractClass = isAbstractClass;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setParent(ModelElement parent) {
		this.parent = parent;
	}

	public void addAttribute(ClassVariable newAttribute) {
		if (attributes.contains(newAttribute))
			throw new IllegalArgumentException("Attribute already present");
		attributes.add(newAttribute);
		firePropertyChange(CHILD, null, newAttribute);
	}

	public void addAttribute(ClassVariable newAttribute, int index) {
		if (attributes.contains(newAttribute))
			throw new IllegalArgumentException("Attribute already present");
		attributes.add(index, newAttribute);
		firePropertyChange(CHILD, null, newAttribute);
	}

	public void addOperation(ClassFunction newOperation) {
		if (operations.contains(newOperation))
			throw new IllegalArgumentException("Operation already present");
		operations.add(newOperation);
		firePropertyChange(CHILD, null, newOperation);
	}

	public void addOperation(ClassFunction newOperation, int index) {
		if (operations.contains(newOperation))
			throw new IllegalArgumentException("Operation already present");
		operations.add(index, newOperation);
		firePropertyChange(CHILD, null, newOperation);
	}

	public void addExtendedClass(UMLClass extendedClass) {
		extendedClasses.add(extendedClass);
		firePropertyChange(ASSOCIATION, null, extendedClass);
	}

	public void addImplementedInterface(UMLInterface implementedInterface) {
		implementedInterfaces.add(implementedInterface);
		firePropertyChange(ASSOCIATION, null, implementedInterface);
	}

	public void removeAttribute(ClassVariable removedAttribute) {
		if (attributes.remove(removedAttribute) == true)
			firePropertyChange(CHILD, removedAttribute, null);
	}

	public void removeOperation(ClassFunction removedOperation) {
		if (operations.remove(removedOperation) == true)
			firePropertyChange(CHILD, removedOperation, null);
	}

	public void removeImplementedInterface(UMLInterface implementedInterface) {
		if (implementedInterfaces.remove(implementedInterface) == true)
			firePropertyChange(ASSOCIATION, implementedInterface, null);
	}

	public void removeExtendedClass(UMLClass extendedClass) {
		if (extendedClasses.remove(extendedClass) == true)
			firePropertyChange(ASSOCIATION, extendedClass, null);
	}

	public String getName() {
		return name;
	}

	public String getVisibility() {
		return visibility;
	}

	public ArrayList<ClassVariable> getAttributes() {
		return attributes;
	}

	public ArrayList<ClassFunction> getOperations() {
		return operations;
	}

	public ArrayList<UMLClass> getExtendedClasses() {
		return extendedClasses;
	}

	public ArrayList<UMLInterface> getImplementedInterfaces() {
		return implementedInterfaces;
	}

	public boolean isAbstract() {
		return isAbstractClass;
	}

	public boolean isInterface() {
		return isInterfaceClass;
	}

	public ModelElement getParent() {
		return parent;
	}

	public Image getIcon() {
		return null;
	}

	public String getLabelText() {
		String labelText = visibility + " ";
		if (isAbstractClass)
			labelText += "<<abstract>> ";
		labelText += name + " ";
		return labelText;
	}

	public String toString() {
		return name;
	}

	public boolean equals(Object o) {
		if ((o == null) || !(o instanceof UMLBaseClass))
			return false;
		UMLBaseClass c = (UMLBaseClass) o;
		String text1 = getLabelText();
		String text2 = c.getLabelText();
		return text1.equals(text2);
	}
}